const uniID = require('uni-id-common') // 引入uni-id-common
const db = uniCloud.database(); // 引入数据库
const getPublicData = uniCloud.importObject('get-public-data'); // 引入获取公共数据
const UniSecCheck = require('uni-sec-check'); // 引入uni-sec-check内容安全公共模块
const contentSafeErrCode = {
	'uni-sec-check-system-error': '系统错误',
	'uni-sec-check-risk-content': '存在风险内容',
	'uni-sec-check-invalid-appid': 'appid错误',
	'uni-sec-check-invalid-appsecret': 'appsecret错误',
	'uni-sec-check-invalid-access-token': 'access_token错误',
	'uni-sec-check-access-token-expired': '登录状态过期',
	'uni-sec-check-invalid-file-type': '错误的文件类型',
	'uni-sec-check-invalid-image-size': '图片大小超出限制',
	'uni-sec-check-invalid-request-url': '请求url错误',
	'uni-sec-check-invalid-request-param': '请求参数错误',
	'uni-sec-check-invalid-request-format': '请求格式错误',
	'uni-sec-check-param-required': '缺少必要参数',
	'uni-sec-check-empty-image': '图片为空',
	'uni-sec-check-empty-content': '内容为空',
	'uni-sec-check-invoke-out-of-limit': '调用次数超出限制'
}

module.exports = {
	_before: async function() { // 通用预处理器
		const methodName = this.getMethodName(); // 获取当前调用的方法名
		const params = this.getParams(); // 获取当前参数列表
		const requestId = this.getUniCloudRequestId(); // 获取请求id
		this.token = await this.getUniIdToken(); // 获取用户token
		if (!this.token) {
			const error = new Error('用户未登录');
			error.code = 401; // 自定义错误码
			error.msg = '用户未登录'; // 自定义错误信息
			throw error;
		}


		const cloudInfo = this.getCloudInfo(); // 获取云端信息
		const clientInfo = this.getClientInfo(); // 获取客户端信息
		this.uniIDIns = await uniID.createInstance({ // 创建uni-id实例
			context: cloudInfo
		});
		this.userInfo = await this.uniIDIns.checkToken(this.token); // 获取用户信息
		if (this.userInfo.code == 30203 || !this.userInfo.uid) {
			const error = new Error('登录状态过期');
			error.code = 401; // 自定义错误码
			error.msg = '登录状态过期'; // 自定义错误信息
			throw error;
		}
		// 检查调用的是否是评论等涉及内容安全的方法(只有微信小程序端有效)
		if (['updateActivityData', 'updateCircleData'].includes(methodName)) {
			// 获取当前用户openid
			const openid = await db.collection('uni-id-users').doc(this.userInfo.uid).field({
				wx_openid: true
			}).get();
			// 初始化实例
			const uniSecCheck = new UniSecCheck({
				provider: 'mp-weixin',
				requestId: this
					.getUniCloudRequestId(), // 云函数内则写 context.requestId 云对象内则写 this.getUniCloudRequestId()
			});
			const checkTextRes = await uniSecCheck.textSecCheck({
				content: methodName == 'updateActivityData' ? params[0].title + params[0].content :
					methodName == 'updateCircleData' ? params[0].title + params[0].content :
					'', // 文本内容，不可超过500KB
				openid: openid.data[0].wx_openid.mp,
				version: 2 // 接口版本号
			});
			if (checkTextRes.errCode != 0) {
				const error = new Error(contentSafeErrCode[checkTextRes.errCode]);
				error.code = 403;
				error.msg = contentSafeErrCode[checkTextRes.errCode];
				throw error;
			}
			if (checkTextRes.result.suggest != 'pass') {
				const error = new Error(`内容存在${checkTextRes.result.label}信息`);
				error.code = 403;
				error.msg = `内容存在${checkTextRes.result.label}信息`;
				throw error;
			}
			// 检查图片内容
			const checkImgRes = await uniSecCheck.imgSecCheck({
				image: methodName == 'updateActivityData' ? params[0].imgUrl[0].url : methodName ==
					'updateCircleData' ? params[0].imgs[0].url : '', // 图片文件url
				openid: openid.data[0].wx_openid.mp,
				version: 2 // 接口版本号
			});
			if (checkImgRes.errCode != 0) {
				const error = new Error(contentSafeErrCode[checkImgRes.errCode]);
				error.code = 403;
				error.msg = contentSafeErrCode[checkImgRes.errCode];
				throw error;
			}
		}
		// console.log('User Data:', JSON.stringify(this.userInfo, null, 2)); // 更清晰地打印对象
	},

	/**
	 * 取消报名
	 * @param {string} activity_id:活动id
	 * @returns {object} 返回结果
	 */
	async cancelSignUp(activity_id) {
		const nowTime = new Date();
		// 判断参数是否为空
		if (!activity_id) {
			throw new Error('参数不能为空');
		}
		//判断活动是否存在
		const activity = await getPublicData.getActivityDetail(activity_id);
		if (!activity.data.length) {
			throw new Error('活动不存在');
		}
		// 判断活动是否已经开始，不能取消报名
		if (nowTime > activity.data[0].start_time) {
			throw new Error('活动已开始');
		}


		// 判断用户是否已经报名
		const signup = await db.collection('qmy-activity-sign-up').where({
			activity_id: activity_id,
			user_id: this.userInfo.uid
		}).get();
		if (!signup.data.length || signup.data[0].signup_status == 1) {
			throw new Error('您未报名');
		}
		// 查看活动是否为付费活动
		if (activity.data[0]?.is_pay) {
			// 查看当前时间是否是活动开始前24小时
			let timeStatus = true;
			const startTime = new Date(activity.data[0].start_time);
			if (nowTime > startTime - 24 * 60 * 60 * 1000) {
				timeStatus = false;
			}
			// 查看报名数据关联的支付订单是否是已付款
			const order = await db.collection('uni-pay-orders').where({
				out_trade_no: signup.data[0].order_id
			}).get();
			// 如果不存在订单，则返回错误
			if (!order.data[0]) {
				throw new Error('支付订单不存在');
			}
			if (order.data[0].status == 1) {
				// custom增加退款原因字段
				order.data[0].custom.refund_reason = timeStatus ? '用户申请取消报名，系统自动申请退款，等待管理员审核' :
					'用户在活动开始前24小时后申请取消报名，系统自动申请退款，等待管理员审核';
				// 更改订单状态为退款中
				await db.collection('uni-pay-orders').where({
					out_trade_no: signup.data[0].order_id
				}).update({
					status: 4,
					custom: order.data[0].custom
				});
				// 查看超级管理员用户的id
				const superAdmin = await db.collection('uni-id-users').where({
					role: 'admin'
				}).field({
					_id: true
				}).get();
				// 发送系统通知给用户
				await db.collection('qmy-notice').add({
					notice_type: 0,
					system_notice_type: '活动退款通知',
					notice_title: activity.data[0].name + '活动退款通知',
					notice_content: timeStatus ?
						`我们已收到您关于“${activity.data[0].name}”活动的取消报名申请，我们将在24小时内为您处理并将报名费用原路退回您的支付账户，请耐心等待。` :
						`我们已收到您关于“${activity.data[0].name}”活动的取消报名申请，因您在活动开始前24小时后取消报名，您需尽快主动联系平台客服协商处理，多谢理解。`,
					user_id: superAdmin.data[0]._id,
					receive_user_id: this.userInfo.uid,
					user_read_status: 0,
					notice_time: Date.now(),
				});
				return {
					code: 200,
					msg: '申请已提交，请您留意系统通知'
				}
			} else if (order.data[0].status == 4) {
				return {
					code: 200,
					msg: '我们将在24小时内处理您的申请，请您留意系统通知'
				}
			}
		} else {
			// 取消报名
			const res = await db.collection('qmy-activity-sign-up').where({
				_id: signup.data[0]._id
			}).update({
				signup_status: 1
			});
			return {
				code: 200,
				data: res,
				msg: '取消报名成功'
			}
		}

	},
	/**
	 * 编辑活动
	 * @param {string} data:活动数据
	 * @returns {object} 返回编辑状态
	 */
	async updateActivityData(data) {
		// 判断是否是组织者
		const userInfo = await db.collection('uni-id-users').where({
			_id: this.userInfo.uid
		}).field({
			role: true
		}).get();
		if (!userInfo?.data[0]?.role?.includes('organizer')) {
			let error = new Error('您还没有权限编辑活动，快去认证吧');
			error.code = 500;
			error.msg = '您还没有权限编辑活动，快去认证吧';
			throw error;
		}
		if (!data.title) {
			throw new Error('标题不能为空');
		}
		if (!data.content) {
			throw new Error('内容不能为空');
		}
		if (!data.imgUrl) {
			throw new Error('图片不能为空');
		}
		if (data.imgUrl.length > 6) {
			throw new Error('图片不能大于6张');
		}
		if (!data.activityType) {
			throw new Error('活动分类不能为空');
		}
		if (!data.signUpSTime) {
			throw new Error('报名开始时间不能为空');
		}
		if (!data.signUpETime) {
			throw new Error('报名结束时间不能为空');
		}
		if (!data.activitySTime) {
			throw new Error('活动开始时间不能为空');
		}
		if (!data.activityETime) {
			throw new Error('活动结束时间不能为空');
		}
		if (!data.latitude) {
			throw new Error('经度不能为空');
		}
		if (!data.longitude) {
			throw new Error('纬度不能为空');
		}
		if (!data.activityLocation) {
			throw new Error('活动地点不能为空');
		}
		if (!data.activityPeople) {
			throw new Error('活动人数不能为空');
		}
		if (data.activityIsPay) {
			// 如果活动是否付费为true，检查付费金额是否为整数
			const payIsInteger = /^[0-9]+$/.test(data.activityPay);
			if (!payIsInteger || Number(data.activityPay) <= 0) {
				throw new Error('付费金额必须为整数');
			}
		}

		// 转换报名时间和活动时间为时间戳
		const signUpSTime = new Date(data.signUpSTime).getTime(); // 报名开始时间
		const signUpETime = new Date(data.signUpETime).getTime(); // 报名结束时间
		const activitySTime = new Date(data.activitySTime).getTime(); // 活动开始时间
		const activityETime = new Date(data.activityETime).getTime(); // 活动结束时间
		const activityPeople = parseInt(data.activityPeople); // 活动人数
		const activityPay = parseFloat(data.activityPay || 0); // 付费金额
		// 如果报名开始时间大于报名结束时间
		if (signUpSTime > signUpETime) {
			throw new Error('报名开始时间不能大于报名结束时间');
		}
		// 如果活动开始时间大于活动结束时间
		if (activitySTime > activityETime) {
			throw new Error('活动开始时间不能大于活动结束时间');
		}
		// 如果活动开始时间小于报名结束时间
		if (activitySTime < signUpETime) {
			throw new Error('活动开始时间不能小于报名结束时间');
		}
		// 检查活动人数是否为整数
		const peopleIsInteger = /^[0-9]+$/.test(data.activityPeople);
		if (!peopleIsInteger || Number(data.activityPeople) <= 0) {
			throw new Error('活动人数不能为负数');
		}
		// 查看此用户的用户信息检查是否存在联系方式
		const user = await db.collection('uni-id-users').where({
			_id: this.userInfo.uid
		}).get();
		if (!user.data[0].mobile) {
			const error = new Error('请先完善联系方式');
			error.code = 400;
			error.msg = '请先完善联系方式';
			throw error;
		}
		// 往图片数组里加入src，值为url的值,异步用for()
		for (let i = 0; i < data.imgUrl.length; i++) {
			data.imgUrl[i].src = data.imgUrl[i].url;
		}
		// 如果社群二维码不为空，则为社群二维码数组里的每条加上src
		if (data.groupCodeImg.length) {
			for (let i = 0; i < data.groupCodeImg.length; i++) {
				data.groupCodeImg[i].src = data.groupCodeImg[i].url;
			}
		}

		// 判断活动是否存在
		const activity = await getPublicData.getActivityDetail(data.activityId);
		if (!activity.data.length) {
			throw new Error('活动不存在');
		}
		// 判断活动的发布者是否是当前用户
		if (activity.data[0].user_id !== this.userInfo.uid) {
			throw new Error('您无权限编辑此活动');
		}
		// 判断活动是否在进行中，进行中的活动不能被编辑
		if (activity.data[0].start_time < new Date() && activity.data[0].end_time > new Date()) {
			throw new Error('活动正在进行中，不能被修改');
		}
		// 判断活动是否已结束，已结束的活动不能被编辑
		if (activity.data[0].end_time < new Date()) {
			throw new Error('活动已结束，不能被修改');
		}
		// 如果是付费活动且报名已开启不能被编辑
		if (activity.data[0].is_pay && activity.data[0].signup_start_time < new Date()) {
			throw new Error('付费活动报名已开启，不能被修改');
		}
		// 如果是管理端新增的活动，提示用户到管理端编辑
		if (!activity.data[0].imgs[0].uuid) {
			throw new Error('该活动为管理端创建，请到管理端编辑');
		}
		// 如果是免费活动且报名已经开始，不能改为付费活动
		if (!activity.data[0].is_pay && activity.data[0].signup_start_time < new Date()) {
			throw new Error('免费活动报名已开启，不能改为付费活动');
		}
		// 查询此活动的报名数据，活动人数不能小于报名人数
		const signup = await db.collection('qmy-activity-sign-up').where({
			activity_id: data.activityId,
			signup_status: 0
		}).get();
		if (activityPeople < signup.data.length) {
			throw new Error('活动人数不能小于报名人数');
		}
		// 保存活动数据
		await db.collection('qmy-activity').doc(data.activityId).update({
			name: data.title, // 活动名称
			content: data.content, // 活动详情
			imgs: data.imgUrl, // 活动图片
			tags: data.activityTag, // 活动标签
			type: data.activityType, // 活动分类
			signup_start_time: signUpSTime, // 报名开始时间
			signup_end_time: signUpETime, // 报名结束时间
			start_time: activitySTime, // 活动开始时间
			end_time: activityETime, // 活动结束时间
			location: data.activityLocation, // 活动地点
			location_lat: String(data.latitude), // 纬度
			location_lng: String(data.longitude), // 经度
			is_pay: data.activityIsPay, // 活动是否付费
			pay_amount: activityPay, // 付费金额
			people_num: activityPeople, // 活动人数
			group_qrcode: data.groupCodeImg, // 社群二维码
			audit_status: 0 // 恢复审核状态
		});
		return {
			code: 200,
			msg: '修改成功，等待审核通过后展示'
		}
	},
	/**
	 * 修改圈子
	 * @param {string} title:标题
	 * @param {string} content:内容
	 * @param {string} activityId:活动id
	 * @param {array} imgs:图片
	 * @returns {object} 返回修改状态
	 */
	async updateCircleData(data) {
		if (!data.title) {
			throw new Error('标题不能为空');
		}
		if (!data.content) {
			throw new Error('内容不能为空');
		}
		if (!data.imgs) {
			throw new Error('图片不能为空');
		}
		// 判断图片是否大于6张
		if (data.imgs.length > 6) {
			throw new Error('图片不能大于6张');
		}
		// 判断标题是否大于23个字
		if (data.title.length > 23) {
			throw new Error('标题不能大于23个字符');
		}
		// 判断圈子是否存在
		const circle = await db.collection('uni-cms-articles').where({
			_id: data.id,
			user_id: this.userInfo.uid
		}).get();
		if (!circle.data.length) {
			throw new Error('圈子不存在');
		}
		// 判断圈子发布者是否是当前用户
		if (circle.data[0].user_id !== this.userInfo.uid) {
			throw new Error('您无权限编辑此圈子');
		}
		// 判断是否存在imgs_info，如果不存在则为管理端发布，请到管理端编辑
		if (!circle.data[0].imgs_info) {
			throw new Error('该圈子为管理端发布，请到管理端编辑');
		}
		// 取出每个imgs里的url
		const imgs = data.imgs.map(item => item.url);
		// 保存数据
		await db.collection('uni-cms-articles').doc(data.id).update({
			activity_id: data.activityId, // 活动id
			title: data.title, // 标题
			content: data.content, // 内容
			imgs_info: data.imgs, //适配圈子修改时读取用
			thumbnail: imgs, // 缩略图
			last_modify_date: Date.now(), // 修改时间
			last_modify_ip: this.clientInfo?.clientIP || '127.0.0.1', // 修改ip
			audit_status: 0, // 恢复审核状态
		});
		return {
			code: 200,
			msg: '修改成功，等待审核通过后展示'
		}
	},
	/**
	 * 删除圈子
	 * @param {string} id:圈子id
	 * @returns {object} 返回删除状态
	 */
	async deleteCircle(id) {
		// 判断圈子是否存在
		const circle = await getPublicData.getCircleDetail(id);
		if (!circle.data.length) {
			throw new Error('圈子不存在');
		}
		// 判断圈子发布者是否是当前用户
		if (circle.data[0].user_id !== this.userInfo.uid) {
			throw new Error('您无权限删除此圈子');
		}
		// 删除圈子
		await db.collection('uni-cms-articles').doc(id).remove();
		return {
			code: 200,
			msg: '删除成功'
		}
	},
	/**
	 * 更新活动消息已读状态
	 * @param {string} id:消息id
	 * @returns {object} 返回更新状态
	 */
	async updateActivityNoticeReadStatus(id) {
		// 判断消息是否存在
		const notice = await db.collection('qmy-notice').doc(id).get();
		if (!notice.data.length) {
			throw new Error('消息不存在');
		}
		// 判断已读用户数组中是否存在当前用户id
		if (notice.data[0].user_read_status_array.includes(this.userInfo.uid)) {
			throw new Error('消息已读');
		}
		// 如果已读用户数组为空，则添加当前用户id
		if (!notice.data[0].user_read_status_array) {
			notice.data[0].user_read_status_array = [this.userInfo.uid];
		} else {
			notice.data[0].user_read_status_array.push(this.userInfo.uid);
		}
		// 更新消息已读状态
		await db.collection('qmy-notice').doc(id).update({
			user_read_status_array: notice.data[0].user_read_status_array
		});
		return {
			code: 200,
			msg: '状态更新成功'
		}
	},
	/**
	 * 更新所有系统通知为已读状态
	 * @returns {object} 返回更新状态
	 */
	async updateSystemNoticeReadStatus() {
		await db.collection('qmy-notice').where({
			notice_type: 0, // 系统通知
			user_read_status: 0, // 未读
			receive_user_id: this.userInfo.uid // 接收用户id
		}).update({
			user_read_status: 1 // 已读
		});
		return {
			code: 200,
			msg: '状态更新成功'
		}
	}
}